/**
 ******************************************************************************
 * @file           : psv.c
 * @brief          : Periodic Signal Validator Implementation
 ******************************************************************************
 * @attention
 *
 * Copyright (c) 2025 PSV Project
 * SPDX-License-Identifier: MIT
 *
 * 周期信号验证器实现
 *
 * 算法原理：
 * 1. 周期规律性检测：计算连续N个周期的变异系数CV
 * 2. 频率范围检查：只接受量程内的频率
 * 3. 频率变化率限制：限制频率变化速度
 * 4. 连续稳定判断：连续通过才认为有效
 *
 * 核心公式：
 * CV = 标准差 / 均值
 * - 真实信号：CV < 0.1（周期非常均匀）
 * - 干扰信号：CV > 0.3（周期杂乱无章）
 *
 ******************************************************************************
 */

/* Includes ------------------------------------------------------------------*/
#include "psv.h"

/* Private typedef -----------------------------------------------------------*/

/**
 * @brief   周期缓冲区结构
 */
typedef struct
{
    uint32_t periods[PSV_PERIOD_WINDOW_SIZE];   /*!< 周期缓存（微秒） */
    uint8_t index;                              /*!< 当前索引 */
    uint8_t count;                              /*!< 有效数据数量 */
} PeriodBuffer_t;

/**
 * @brief   PSV检测状态
 */
typedef struct
{
    PeriodBuffer_t period_buf;      /*!< 周期缓冲区 */
    uint32_t last_freq;             /*!< 上次频率（Hz） */
    uint32_t last_time_ms;          /*!< 上次时间戳（ms） */
    uint8_t stable_count;           /*!< 连续稳定计数 */
    uint8_t is_locked;              /*!< 信号锁定标志 */
} PSV_State_t;

/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static PSV_State_t s_state = {0};   /*!< 检测状态 */

/* Private function prototypes -----------------------------------------------*/
static float calculate_period_cv(PeriodBuffer_t *buf, float *mean_out, float *std_dev_out);
static uint8_t check_freq_range(uint32_t freq);
static uint8_t check_freq_change_rate(uint32_t freq, uint32_t time_ms);
static uint8_t check_period_regularity(uint32_t freq);

/* Private functions ---------------------------------------------------------*/

/**
 * @brief       计算周期变异系数（CV = 标准差 / 均值）
 *
 * @param[in]   buf: 周期缓冲区指针
 * @param[out]  mean_out: 输出平均值（可选）
 * @param[out]  std_dev_out: 输出标准差（可选）
 *
 * @retval      变异系数（0.0 ~ 1.0+）
 *
 * @note        CV越小表示周期越规律
 *              真实信号 CV < 0.1，干扰信号 CV > 0.3
 */
static float calculate_period_cv(PeriodBuffer_t *buf, float *mean_out, float *std_dev_out)
{
    if (buf == NULL || buf->count < 3)
    {
        return 999.0f;  /* 数据不足，返回极大值 */
    }

    /* 计算平均值 */
    uint32_t sum = 0;
    for (uint8_t i = 0; i < buf->count; i++)
    {
        sum += buf->periods[i];
    }
    float mean = (float)sum / buf->count;

    /* 计算标准差 */
    float variance = 0.0f;
    for (uint8_t i = 0; i < buf->count; i++)
    {
        float diff = (float)buf->periods[i] - mean;
        variance += diff * diff;
    }
    float std_dev = PSV_SQRTF(variance / buf->count);

    /* 计算变异系数 */
    float cv = std_dev / mean;

    /* 输出参数 */
    if (mean_out != NULL) *mean_out = mean;
    if (std_dev_out != NULL) *std_dev_out = std_dev;

    PSV_LOG_D("CV=%.3f (threshold=%.3f), Mean=%.1f, StdDev=%.1f",
              cv, PSV_PERIOD_CV_THRESHOLD, mean, std_dev);

    return cv;
}

/**
 * @brief       检查频率是否在有效范围内
 *
 * @param[in]   freq: 频率（Hz）
 *
 * @retval      1=在范围内，0=超出范围
 */
static uint8_t check_freq_range(uint32_t freq)
{
    if (freq < PSV_FREQ_MIN_HZ || freq > PSV_FREQ_MAX_HZ)
    {
        PSV_LOG_W("Freq out of range: %lu Hz", (unsigned long)freq);
        return 0;
    }
    return 1;
}

/**
 * @brief       检查频率变化率
 *
 * @param[in]   freq: 当前频率（Hz）
 * @param[in]   time_ms: 当前时间戳（ms）
 *
 * @retval      1=变化率正常，0=变化率超限
 *
 * @note        真实流量变化缓慢，干扰导致频率跳变剧烈
 */
static uint8_t check_freq_change_rate(uint32_t freq, uint32_t time_ms)
{
    /* 首次检测，直接通过 */
    if (s_state.last_freq == 0)
    {
        s_state.last_freq = freq;
        s_state.last_time_ms = time_ms;
        return 1;
    }

    /* 计算时间间隔 */
    float dt = (float)(time_ms - s_state.last_time_ms) / 1000.0f;  /* 转换为秒 */
    if (dt < 0.001f)
    {
        return 1;  /* 时间间隔太小，跳过检测 */
    }

    /* 计算频率变化率 */
    float freq_change = PSV_FABSF((float)freq - (float)s_state.last_freq);
    float change_rate = freq_change / dt;  /* Hz/s */

    PSV_LOG_D("ChangeRate=%.1f Hz/s (limit=%.1f)",
              change_rate, PSV_FREQ_CHANGE_RATE_MAX_HZ_S);

    /* 更新历史数据 */
    s_state.last_freq = freq;
    s_state.last_time_ms = time_ms;

    /* 判断是否超限 */
    if (change_rate > PSV_FREQ_CHANGE_RATE_MAX_HZ_S)
    {
        PSV_LOG_W("Freq change too fast!");
        return 0;
    }

    return 1;
}

/**
 * @brief       检查周期规律性
 *
 * @param[in]   freq: 当前频率（Hz）
 *
 * @retval      1=周期规律，0=周期不规律
 *
 * @note        将频率转换为周期，存入缓冲区，计算变异系数
 */
static uint8_t check_period_regularity(uint32_t freq)
{
    /* 频率转周期（微秒） */
    uint32_t period_us = (freq > 0) ? (1000000 / freq) : 0;

    if (period_us == 0)
    {
        return 0;
    }

    /* 存入循环缓冲区 */
    s_state.period_buf.periods[s_state.period_buf.index] = period_us;
    s_state.period_buf.index = (s_state.period_buf.index + 1) % PSV_PERIOD_WINDOW_SIZE;

    /* 更新有效数据数量 */
    if (s_state.period_buf.count < PSV_PERIOD_WINDOW_SIZE)
    {
        s_state.period_buf.count++;
    }

    /* 数据不足，暂时通过 */
    if (s_state.period_buf.count < PSV_PERIOD_WINDOW_SIZE / 2)
    {
        return 1;
    }

    /* 计算变异系数 */
    float cv = calculate_period_cv(&s_state.period_buf, NULL, NULL);

    /* 判断是否规律 */
    if (cv > PSV_PERIOD_CV_THRESHOLD)
    {
        PSV_LOG_W("Period irregular! CV=%.3f > %.3f (REJECTED)",
                  cv, PSV_PERIOD_CV_THRESHOLD);
        return 0;
    }

    PSV_LOG_D("Period regular, CV=%.3f < %.3f (PASS)",
              cv, PSV_PERIOD_CV_THRESHOLD);
    return 1;
}

/* Exported functions --------------------------------------------------------*/

/**
 * @brief       初始化PSV模块
 *
 * @param       无
 *
 * @retval      无
 */
void psv_init(void)
{
    PSV_MEMSET(&s_state, 0, sizeof(s_state));
    PSV_LOG_I("PSV Module initialized (v1.0.0)");
}

/**
 * @brief       检测频率信号质量
 *
 * @param[in]   freq_hz: 当前频率（Hz）
 *
 * @retval      1=有效信号，0=干扰信号
 *
 * @note        综合判断：频率范围 + 变化率 + 周期规律性 + 连续稳定
 */
uint8_t psv_check(uint32_t freq_hz)
{
#if !PSV_ENABLE
    /* 功能关闭，直接返回有效 */
    return PSV_VALID;
#else
    uint8_t is_valid = 1;
    uint32_t current_time_ms = PSV_GET_TICK_MS();

    /* 1. 频率范围检查 */
    if (!check_freq_range(freq_hz))
    {
        is_valid = 0;
    }

    /* 2. 频率变化率检查 */
    if (is_valid && !check_freq_change_rate(freq_hz, current_time_ms))
    {
        is_valid = 0;
    }

    /* 3. 周期规律性检查 */
    if (is_valid && !check_period_regularity(freq_hz))
    {
        is_valid = 0;
    }

    /* 4. 连续稳定判断 */
    if (is_valid)
    {
        s_state.stable_count++;
        if (s_state.stable_count >= PSV_STABLE_COUNT_MIN)
        {
            s_state.is_locked = 1;  /* 信号锁定 */
            PSV_LOG_I("Signal LOCKED (stable=%u)", s_state.stable_count);
        }
    }
    else
    {
        /* 检测失败，重置计数器 */
        s_state.stable_count = 0;
        s_state.is_locked = 0;
        PSV_LOG_D("Signal INVALID");
    }

    /* 返回信号是否锁定 */
    return s_state.is_locked;
#endif
}

/**
 * @brief       复位PSV检测状态
 *
 * @param       无
 *
 * @retval      无
 *
 * @note        当信号消失或超时时调用
 */
void psv_reset(void)
{
    PSV_MEMSET(&s_state, 0, sizeof(s_state));
    PSV_LOG_D("PSV state reset");
}

/**
 * @brief       获取PSV统计信息
 *
 * @param[out]  stats: 统计信息指针
 *
 * @retval      无
 *
 * @note        用于调试和监控
 */
void psv_get_statistics(PSV_Statistics_t *stats)
{
    if (stats == NULL)
    {
        return;
    }

    float mean = 0.0f;
    float std_dev = 0.0f;
    stats->cv = calculate_period_cv(&s_state.period_buf, &mean, &std_dev);
    stats->mean_period_us = mean;
    stats->std_dev_us = std_dev;
    stats->sample_count = s_state.period_buf.count;
    stats->is_locked = s_state.is_locked;
}
